package ATM;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class BankDatabase 
{
	private Account[] accounts =  	new Account[] {	new Account(12345, 54321, 1000.0), // using two accounts to exemplify the application
													new Account(98765, 56789, 200.0)}; 
	
	private static final Logger fLogger = Logger.getLogger(BankDatabase.class.getPackage().getName());
	//using Java's logging facilities to record exceptions
	
	public BankDatabase()
	{
		List<Account> list = Arrays.asList(accounts); // use of collections: List of Accounts objects 
		
		 try          //exception handling on 2 levels
		 {
		      //use buffering
		      OutputStream file = new FileOutputStream( "list.txt" ); //the output stream records the Account objects in list.txt 
		      OutputStream buffer = new BufferedOutputStream( file );
		      ObjectOutput output = new ObjectOutputStream( buffer );
		      try
		      {
		        output.writeObject(list);
		      }
		      finally
		      {
		        output.close();
		      }
		}  
		    catch(IOException ex)
		    {
		      fLogger.log(Level.SEVERE, "Cannot perform output.", ex);
		    }
		
		 try
		 {
		      //using buffering
		      InputStream file = new FileInputStream( "list.txt" ); //the application can read Account objects from the file and used them  
		      InputStream buffer = new BufferedInputStream( file );
		      ObjectInput input = new ObjectInputStream ( buffer );
		      try
		      {
		        //deserialize the List
		        List<Account> recoveredAccounts = (List<Account>)input.readObject();
		        //display its data
		        for(Account theAccount: recoveredAccounts)
		        {
		          System.out.print("Recovered Account: " + theAccount); 
		          System.out.printf("\nThe account number is: %d\n", theAccount.getAccountNumber()); // we can extract and display information regarding each account
		        }
		      }
		      finally
		      {
		        input.close();
		      }
		  }
		    catch(ClassNotFoundException ex)
		    {
		      fLogger.log(Level.SEVERE, "Cannot perform input. Class not found.", ex);
		    }
		    catch(IOException ex)
		    {
		      fLogger.log(Level.SEVERE, "Cannot perform input.", ex);
		    }
		 }		
		
	
	private Account getAccount(int accountNumber)
	{
		for (Account currentAccount: accounts)
		{
			if (currentAccount.getAccountNumber() == accountNumber)
				return currentAccount;
		}
		
		return null;
	}
	
	public boolean authenticateUser(int userAccountNumber, int userPIN) //checks whether the logged user is identified by the bank database
	{
		Account userAccount = getAccount(userAccountNumber);
		
		if (userAccount != null)
			return userAccount.validatePIN(userPIN);
		else
			return false;
	}
	
	public double getAvailableBalance(int userAccountNumber)		//getAvailableBalance(), credit() and debit() have access to Accounts only through get() methods
	{
		return getAccount(userAccountNumber).getAvailableBalance();
	}
		
	public void credit(int userAccountNumber, double amount)
	{
		getAccount(userAccountNumber).credit(amount);
	}
	
	public void debit(int userAccountNumber, double amount)
	{
		getAccount(userAccountNumber).debit(amount);
	}
}